
#include <BChangeEvent>
#include "IWindow.h"
#include "IGlobal.h"
#include "ISockets.h"
#include "member_BDrag.h"
#include "member_BWidget.h"

using namespace BWE;

bool			app_done = false;
int				app_code = 0;
int 			app_realFrequency = 0;
int				app_frequency = 30;
clock_t			app_timeCounter = 0;
double			app_lastRenderTime = 0;
BClock			app_frequencyTimer;

BArray<BString>			app_pluginPaths;
BArray<BString>			app_fontPaths;
BArray<BString>			app_dataPaths;

BString					app_styleSheet;
BHolder<IStyleDriver>	app_styleDriver;
BHolder<BStyle>			app_style;
BList<IWindowHolder>	app_windows;

bool App_AttachWindow(BWidget* widget)
{
	if (!widget)
		return 0;
	IWindow* window = 0;
	for (int i = 0; i < app_windows.size(); i++)
	{
		IWindow* w = app_windows[i];
		if (w->boss == 0)
		{
			window = app_windows[i];
			window->boss = widget;
			break;
		}
	}
	if (!window)
	{
		window = new IWindow(widget);
	}
	widget_member(widget)->window = window;
	widget_member(widget)->applyStyleDriver();
	BChangeEvent event(Change_Style);
	event.setStyle(app_style);
	widget_member(widget)->changeStyle(event);
	return true;
}
bool App_DetachWindow(IWindow* window)
{
	if (window)
	{
		window->close_time = clock();
		window->hideWindow();
		window->boss = 0;
		window = 0;
	}
	return true;
}

void App_CycleBegin()
{
	app_frequencyTimer.start();
}
void App_Event(IWindow* window)
{
#ifdef _LINUX_
	XEvent event;
	while (XPending(display))
	{
		XNextEvent(display, &event);
		const XAnyEvent& any = (const XAnyEvent&)event;
		if (any.window == window)
		{
			procEvent(event);
		}
	};
#endif
#ifdef _WINDOWS_SYSTEM_
	HWND hwnd = 0;
	if (window)
		hwnd = window->hwnd;
	MSG msg;
	while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
#endif
}
void App_Event(BDrag* drag)
{
	if (!drag)
		return;
	static BDragEvent dragEvent;
	dragEvent.setDrag(drag);
	MSG msg;
	while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
	{
		if (msg.message == 0)
			break;
		if (msg.message == WM_QUIT)
			break;
		TranslateMessage(&msg);
		for (int i = 0; i < app_windows.size(); i++)
		{
			IWindow* window = app_windows[i];
			if (window->hwnd == msg.hwnd)
			{
				if (msg.message == WM_MOUSEMOVE)
				{
					BPoint absolutePos((short)LOWORD(msg.lParam), (short)HIWORD(msg.lParam));
					dragEvent.setAbsolutePos(absolutePos);
					window->procDragMove(dragEvent);
				}
				if (msg.message == WM_LBUTTONUP)
				{
					dragEvent.setType(Event_DragDrop);
					window->procDragDrop(dragEvent);
					drag_member(drag)->over = true;
					dragEvent.setDrag(0);
				}
				break;
			}
		}
	}
}
void App_Update()
{
	for (int i = 0; i < app_windows.size(); i++)
	{
		IWindow* window = app_windows[i];
		if (!window->boss)
			continue;
		if (window->boss->able())
		{
			window->update();
		}
	}
}
void App_Frame()
{
	if (app_windows.empty())
		return;
	IWindow* firstWindow = app_windows.first();
	for (int i = 1; i < app_windows.size(); i++)
	{
		IWindow* window = app_windows[i];
		if (!window->shared)
		{
			wglShareLists(firstWindow->context, window->context);
			window->shared = true;
		}
	}
	for (int i = 0; i < app_windows.size(); i++)
	{
		IWindow* window = app_windows[i];
		if (!window->boss)
			continue;
		if (window->boss->able() && window->boss->visible())
		{
			window->fresh();
			window->frame();
		}
	}
}
void App_CycleEnd()
{
	static int frameCount = 0;
	frameCount++;
	clock_t now = clock();
	if (now - app_timeCounter > 1000)
	{
		app_timeCounter = now;
		app_realFrequency = frameCount;
		frameCount = 0;
	}

	for (int i = 0; i < app_windows.size(); i++)
	{
		IWindow* window = app_windows[i];
		if (!window->boss && now - window->close_time > 360000)
		{
			app_windows.remove(i--);
		}
	}

	App_SelectSocket();

	double time = app_frequencyTimer.stop();
	double sleepTime = 1.0 / app_frequency - time;
	if (sleepTime > 0)
	{
		app_frequencyTimer.sleep(sleepTime);
	}
}

